/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define  YY_INT_ALIGNED short int

/* A lexical scanner generated by flex */
#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 6
#define YY_FLEX_SUBMINOR_VERSION 4
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif

/* The c++ scanner is a mess. The FlexLexer.h header file relies on the
 * following macro. This is required in order to pass the c++-multiple-scanners
 * test in the regression suite. We get reports that it breaks inheritance.
 * We will address this in a future release of flex, or omit the C++ scanner
 * altogether.
 */
#define yyFlexLexer script_FlexLexer

#ifdef yyalloc
#define script_alloc_ALREADY_DEFINED
#else
#define yyalloc script_alloc
#endif

#ifdef yyrealloc
#define script_realloc_ALREADY_DEFINED
#else
#define yyrealloc script_realloc
#endif

#ifdef yyfree
#define script_free_ALREADY_DEFINED
#else
#define yyfree script_free
#endif

/* First, we deal with  platform-specific or compiler-specific issues. */
/* begin standard C++ headers. */
#include <iostream>
#include <errno.h>
#include <cstdlib>
#include <cstdio>
#include <cstring>
/* end standard C++ headers. */

/* flex integer type definitions */
#ifndef YYFLEX_INTTYPES_DEFINED
#define YYFLEX_INTTYPES_DEFINED

/* Prefer C99 integer types if available. */
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
/* Include <inttypes.h> and not <stdint.h> because Solaris 2.6 has the former
 * and not the latter.
 */
#include <inttypes.h>
#define YYFLEX_USE_STDINT
#else
#if defined(_MSC_VER) && _MSC_VER >= 1600

/* Visual C++ 2010 does not define __STDC_VERSION__ and has <stdint.h> but not
 * <inttypes.h>.
 */
#include <stdint.h>
#define YYFLEX_USE_STDINT
#endif
#endif
#ifdef YYFLEX_USE_STDINT
typedef int8_t flex_int8_t;
typedef uint8_t flex_uint8_t;
typedef int16_t flex_int16_t;
typedef uint16_t flex_uint16_t;
typedef int32_t flex_int32_t;
typedef uint32_t flex_uint32_t;
#else
typedef unsigned char flex_uint8_t;
typedef short int flex_int16_t;
typedef unsigned short int flex_uint16_t;
#ifdef __STDC__
typedef signed char flex_int8_t;

/* ISO C only requires at least 16 bits for int. */
#include <limits.h>
#if UINT_MAX >= 4294967295
#define YYFLEX_INT32_DEFINED
typedef int flex_int32_t;
typedef unsigned int flex_uint32_t;
#endif
#else
typedef char flex_int8_t;
#endif
#ifndef YYFLEX_INT32_DEFINED
typedef long int flex_int32_t;
typedef unsigned long int flex_uint32_t;
#endif
#endif
#endif /* YYFLEX_INTTYPES_DEFINED */

#define yyconst const

#if defined(__GNUC__) && __GNUC__ >= 3
#define yynoreturn __attribute__((__noreturn__))
#else
#define yynoreturn
#endif

/* Returned upon end-of-file. */
#define YY_NULL 0

/* Promotes a possibly negative, possibly signed char to an
 *   integer in range [0..255] for use as an array index.
 */
#define YY_SC_TO_UI(c) ((YY_CHAR)(c))

/* Enter a start condition.  This macro really ought to take a parameter,
 * but we do it the disgusting crufty way forced on us by the ()-less
 * definition of BEGIN.
 */
#define BEGIN (yy_start) = 1 + 2 *

/* Translate the current start state into a value that can be later handed
 * to BEGIN to return to the state.  The YYSTATE alias is for lex
 * compatibility.
 */
#define YY_START (((yy_start)- 1) / 2)
#define YYSTATE YY_START

/* Action number for EOF rule of a given start state. */
#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)

/* Special action meaning "start processing a new file". */
#define YY_NEW_FILE yyrestart(yyin)
#define YY_END_OF_BUFFER_CHAR 0

/* Size of default input buffer. */
#ifndef YY_BUF_SIZE
#ifdef __ia64__
/* On IA-64, the buffer size is 16k, not 8k.
 * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
 * Ditto for the __ia64__ case accordingly.
 */
#define YY_BUF_SIZE 32768
#else
#define YY_BUF_SIZE 16384
#endif /* __ia64__ */
#endif

/* The state buf must be large enough to hold one state per character in the main buffer.
 */
#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))

#ifndef YY_TYPEDEF_YY_BUFFER_STATE
#define YY_TYPEDEF_YY_BUFFER_STATE
typedef struct yy_buffer_state *YY_BUFFER_STATE;
#endif

#ifndef YY_TYPEDEF_YY_SIZE_T
#define YY_TYPEDEF_YY_SIZE_T
typedef size_t yy_size_t;
#endif

extern int yyleng;

#define EOB_ACT_CONTINUE_SCAN 0
#define EOB_ACT_END_OF_FILE 1
#define EOB_ACT_LAST_MATCH 2

#define YY_LESS_LINENO (n)
#define YY_LINENO_REWIND_TO (ptr)

/* Return all but the first "n" matched characters back to the input stream. */
#define yyless(n) \
    do { \
        int yyless_macro_arg = (n); \
        YY_LESS_LINENO(yyless_macro_arg);\
        *yy_cp = (yy_hold_char); \
        YY_RESTORE_YY_MORE_OFFSET \
        (yy_c_buf_p)= yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
        YY_DO_BEFORE_ACTION; /* set up yytext again */ \
    } while (0)
#define unput(c)yyunput(c, (yytext_ptr))

#ifndef YY_STRUCT_YY_BUFFER_STATE
#define YY_STRUCT_YY_BUFFER_STATE
struct yy_buffer_state {
    std::streambuf* yy_input_file;
    char *yy_ch_buf;        /* input buffer */
    char *yy_buf_pos;        /* current position in input buffer */

    /* Size of input buffer in bytes, not including room for EOB
     * characters.
     */
    int yy_buf_size;

    /* Number of characters read into yy_ch_buf, not including EOB
     * characters.
     */
    int yy_n_chars;

    /* Whether we "own" the buffer - i.e., we know we created it,
     * and can realloc()it to grow it, and should free()it to
     * delete it.
     */
    int yy_is_our_buffer;

    /* Whether this is an "interactive" input source; if so, and
     * if we're using stdio for input, then we want to use getc()
     * instead of fread(), to make sure we stop fetching input after
     * each newline.
     */
    int yy_is_interactive;

    /* Whether we're considered to be at the beginning of a line.
     * If so, '^' rules will be active on the next match, otherwise
     * not.
     */
    int yy_at_bol;

    int yy_bs_lineno; /**< The line count. */
    int yy_bs_column; /**< The column count. */

    /* Whether to try to fill the input buffer when we reach the
     * end of it.
     */
    int yy_fill_buffer;

    int yy_buffer_status;

    #define YY_BUFFER_NEW 0
    #define YY_BUFFER_NORMAL 1
    /* When an EOF's been seen but there's still some text to process
     * then we mark the buffer as YY_EOF_PENDING, to indicate that we
     * shouldn't try reading from the input source any more.  We might
     * still have a bunch of tokens to match, though, because of
     * possible backing-up.
     *
     * When we actually see the EOF, we change the status to "new"
     * (via yyrestart()), so that the user can continue scanning by
     * just pointing yyin at a new input file.
     */
    #define YY_BUFFER_EOF_PENDING 2
};
#endif /* !YY_STRUCT_YY_BUFFER_STATE */

/* We provide macros for accessing buffer states in case in the
 * future we want to put the buffer states in a more general
 * "scanner state".
 *
 * Returns the top of the stack, or NULL.
 */
#define YY_CURRENT_BUFFER ((yy_buffer_stack) ? \
    (yy_buffer_stack)[(yy_buffer_stack_top)] : NULL)

/* Same as previous macro, but useful when we know that the buffer stack is not
 * NULL or when we need an lvalue. For internal use only.
 */
#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]

void *yyalloc(yy_size_t size);
void *yyrealloc(void *ptr, yy_size_t size);
void yyfree(void *ptr);

#define yy_new_buffer yy_create_buffer
#define yy_set_interactive(is_interactive)\
    { \
    if (!YY_CURRENT_BUFFER) { \
        yyensure_buffer_stack(); \
        YY_CURRENT_BUFFER_LVALUE = yy_create_buffer(yyin, YY_BUF_SIZE); \
    } \
    YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
    }

#define yy_set_bol(at_bol)\
    { \
    if (!YY_CURRENT_BUFFER) {\
        yyensure_buffer_stack(); \
        YY_CURRENT_BUFFER_LVALUE = yy_create_buffer(yyin, YY_BUF_SIZE); \
    } \
    YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
    }

#define YY_AT_BOL()(YY_CURRENT_BUFFER_LVALUE->yy_at_bol)

/* Begin user sect3 */
#define YY_SKIP_YYWRAP
typedef flex_uint8_t YY_CHAR;

#define yytext_ptr yytext
#define YY_INTERACTIVE

#include <FlexLexer.h>

int yyFlexLexer::yywrap()
{
    return 1;
}

int yyFlexLexer::yylex()
{
    LexerError("yyFlexLexer::yylex invoked but %option yyclass used");
    return 0;
}

#define YY_DECL int Scanner::yylex()

/* Done after the current pattern has been matched and before the
 * corresponding action - sets up yytext.
 */
#define YY_DO_BEFORE_ACTION \
    (yytext_ptr)= yy_bp; \
    yyleng = (int)(yy_cp - yy_bp); \
    (yy_hold_char)= *yy_cp; \
    *yy_cp = '\0'; \
    (yy_c_buf_p)= yy_cp;

#define YY_NUM_RULES 38
#define YY_END_OF_BUFFER 39

/* This struct is not used in this scanner, but its presence is necessary. */
struct yy_trans_info {
    flex_int32_t yy_verify;
    flex_int32_t yy_nxt;
};

static const flex_int16_t yy_accept[90] = {
    0,
    0, 0, 39, 37, 4, 5, 37, 37, 1, 37,
    24, 25, 13, 11, 32, 12, 14, 34, 34, 28,
    22, 15, 20, 33, 33, 33, 33, 33, 33, 33,
    33, 26, 37, 27, 19, 0, 1, 17, 0, 3,
    0, 0, 34, 23, 16, 21, 33, 33, 33, 33,
    33, 33, 9, 33, 33, 18, 36, 0, 0, 0,
    3, 35, 33, 33, 33, 7, 33, 33, 33, 2,
    33, 33, 10, 33, 33, 33, 29, 33, 33, 33,
    8, 33, 33, 31, 33, 33, 30, 6, 0
};

static const YY_CHAR yy_ec[256] = {
    0,
    1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 2, 4, 5, 6, 1, 1, 7, 1, 8,
    9, 10, 11, 12, 13, 14, 15, 16, 17, 17,
    17, 17, 17, 17, 17, 17, 17, 1, 18, 19,
    20, 21, 1, 1, 22, 22, 22, 22, 22, 22,
    22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
    22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
    1, 1, 1, 1, 22, 1, 23, 24, 25, 22,

    26, 27, 22, 28, 29, 22, 30, 31, 22, 32,
    33, 22, 22, 34, 35, 36, 37, 22, 38, 22,
    22, 22, 39, 40, 41, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1,

    1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1
};

static const YY_CHAR yy_meta[42] = {
    0,
    1, 1, 2, 1, 3, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 4, 4, 1, 1, 1,
    1, 4, 4, 4, 4, 4, 4, 4, 4, 4,
    4, 4, 4, 4, 4, 4, 4, 4, 1, 1,
    1
};

static const flex_int16_t yy_base[96] = {
    0,
    0, 0, 125, 126, 126, 126, 104, 0, 0, 116,
    126, 126, 126, 126, 126, 126, 32, 29, 34, 126,
    102, 101, 100, 0, 85, 85, 86, 16, 89, 89,
    86, 126, 73, 126, 126, 107, 0, 126, 42, 0,
    38, 42, 46, 126, 126, 126, 0, 85, 78, 74,
    74, 75, 0, 70, 76, 126, 126, 51, 54, 55,
    0, 51, 81, 67, 76, 0, 76, 63, 68, 126,
    68, 68, 0, 60, 61, 68, 0, 61, 63, 59,
    0, 47, 43, 0, 47, 40, 0, 0, 126, 70,
    74, 40, 78, 82, 86
};

static const flex_int16_t yy_def[96] = {
    0,
    89, 1, 89, 89, 89, 89, 89, 90, 91, 89,
    89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
    89, 89, 89, 92, 92, 92, 92, 92, 92, 92,
    92, 89, 89, 89, 89, 90, 91, 89, 93, 94,
    89, 89, 89, 89, 89, 89, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 89, 89, 93, 95, 93,
    94, 89, 92, 92, 92, 92, 92, 92, 92, 89,
    92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 92, 92, 92, 0, 89,
    89, 89, 89, 89, 89
};

static const flex_int16_t yy_nxt[168] = {
    0,
    4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
    14, 15, 16, 4, 17, 18, 19, 20, 21, 22,
    23, 24, 24, 25, 26, 27, 28, 24, 29, 24,
    24, 24, 24, 30, 24, 24, 24, 31, 32, 33,
    34, 39, 41, 47, 42, 42, 40, 41, 51, 43,
    43, 59, 52, 62, 62, 41, 60, 42, 42, 41,
    59, 43, 43, 59, 59, 60, 62, 62, 70, 60,
    36, 88, 87, 36, 37, 86, 37, 37, 58, 58,
    58, 58, 61, 85, 61, 61, 60, 60, 60, 60,
    84, 83, 82, 81, 80, 79, 78, 77, 76, 75,

    74, 73, 72, 71, 69, 68, 67, 66, 65, 64,
    63, 57, 56, 55, 54, 53, 50, 49, 48, 46,
    45, 44, 38, 35, 89, 3, 89, 89, 89, 89,
    89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
    89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
    89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
    89, 89, 89, 89, 89, 89, 89
};

static const flex_int16_t yy_chk[168] = {
    0,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 17, 18, 92, 18, 18, 17, 19, 28, 19,
    19, 39, 28, 41, 41, 42, 39, 42, 42, 43,
    58, 43, 43, 59, 60, 58, 62, 62, 59, 60,
    90, 86, 85, 90, 91, 83, 91, 91, 93, 93,
    93, 93, 94, 82, 94, 94, 95, 95, 95, 95,
    80, 79, 78, 76, 75, 74, 72, 71, 69, 68,

    67, 65, 64, 63, 55, 54, 52, 51, 50, 49,
    48, 36, 33, 31, 30, 29, 27, 26, 25, 23,
    22, 21, 10, 7, 3, 89, 89, 89, 89, 89,
    89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
    89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
    89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
    89, 89, 89, 89, 89, 89, 89
};

/*
 * The intent behind this definition is that it'll catch
 * any uses of REJECT which flex missed.
 */
#define REJECT reject_used_but_not_detected
#define yymore() yymore_used_but_not_detected
#define YY_MORE_ADJ 0
#define YY_RESTORE_YY_MORE_OFFSET

/*
 * Copyright (c)2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <cerrno>
#include <climits>
#include <string>
#include "parser.hpp"  // 包含由parser.y生成的头文件
#include "scanner.h"   // 包含yyFlexLexer子类的头文件
#include "location.hh" // 包含位置调试信息头文件

/* 定义了YY_USER_ACTION，该宏在每个记号的语义动作之前被调用，来根据记号的长度设置位置的信息 */
#define YY_USER_ACTION  loc.columns (yyleng);

using namespace Uscript;
#define yyterminate()Parser::make_END(loc);
/* 声明使用C++版本FLEXER */
/* 使用Scanner::yylex()*/
/* 一些与编译常量使用该前缀否则为yy */

#define INITIAL 0

#ifndef YY_NO_UNISTD_H
/* Special case for "unistd.h", since it is non-ANSI. We include it way
 * down here because we want the user's section 1 to have been scanned first.
 * The user has a chance to override it with an option.
 */
#include <unistd.h>
#endif

#ifndef YY_EXTRA_TYPE
#define YY_EXTRA_TYPE void *
#endif

#ifndef yytext_ptr
static void yy_flex_strncpy(char *, const char *, int);
#endif

#ifdef YY_NEED_STRLEN
static int yy_flex_strlen(const char *);
#endif
#ifndef YY_NO_INPUT
#endif

/* Amount of stuff to slurp up with each read. */
#ifndef YY_READ_BUF_SIZE
#ifdef __ia64__

/* On IA-64, the buffer size is 16k, not 8k */
#define YY_READ_BUF_SIZE 16384
#else
#define YY_READ_BUF_SIZE 8192
#endif /* __ia64__ */
#endif

/* Copy whatever the last rule matched to the standard output. */
#ifndef ECHO
#define ECHO LexerOutput(yytext, yyleng)
#endif

/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
 * is returned in "result".
 */
#ifndef YY_INPUT
#define YY_INPUT(buf, result, max_size) \
    if ((int)(result = LexerInput((char *)buf, max_size)) < 0)\
        YY_FATAL_ERROR("input in flex scanner failed");
#endif

/* No semi-colon after return; correct usage is to write "yyterminate();" -
 * we don't want an extra ';' after the "return" because that will cause
 * some compilers to complain about unreachable statements.
 */
#ifndef yyterminate
#define yyterminate()return YY_NULL
#endif

/* Number of entries by which start-condition stack grows. */
#ifndef YY_START_STACK_INCR
#define YY_START_STACK_INCR 25
#endif

/* Report a fatal error. */
#ifndef YY_FATAL_ERROR
#define YY_FATAL_ERROR(msg)LexerError(msg)
#endif
/* end tables serialization structures and prototypes */

/* Default declaration of generated scanner - a define so the user can
 * easily add parameters.
 */
#ifndef YY_DECL
#define YY_DECL_IS_OURS 1
#define YY_DECL int yyFlexLexer::yylex()
#endif /* !YY_DECL */

/* Code executed at the beginning of each rule, after yytext and yyleng
 * have been set up.
 */
#ifndef YY_USER_ACTION
#define YY_USER_ACTION
#endif

/* Code executed at the end of each rule. */
#ifndef YY_BREAK
#define YY_BREAK /*LINTED*/break;
#endif

#define YY_RULE_SETUP YY_USER_ACTION

/*
 * The main scanner function which does all the work.
 */
YY_DECL
{
    yy_state_type yy_current_state;
    char *yy_cp;
    char *yy_bp;
    int yy_act;

    if (!(yy_init)) {
        (yy_init)= 1;

#ifdef YY_USER_INIT
    YY_USER_INIT;
#endif
        if (!(yy_start)) {
            (yy_start)= 1;    /* first start state */
        }
        if (!yyin) {
            yyin.rdbuf(std::cin.rdbuf());
        }
        if (!yyout) {
            yyout.rdbuf(std::cout.rdbuf());
        }
        if (!YY_CURRENT_BUFFER) {
            yyensure_buffer_stack();
            YY_CURRENT_BUFFER_LVALUE = yy_create_buffer(yyin, YY_BUF_SIZE);
        }
        yy_load_buffer_state();
    }
    {
    // C++ 兼容的词法分析器的规则，step函数把位置的起始值设置为与结束值相等
    loc.step();
    while (1) {       /* loops until end-of-file is reached */
        yy_cp = (yy_c_buf_p);
        /* Support of yytext. */
        *yy_cp = (yy_hold_char);

        /* yy_bp points to the position in yy_ch_buf of the start of
         * the current run.
         */
        yy_bp = yy_cp;
        yy_current_state = (yy_start);
yy_match:
        do {
            YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
            if (yy_accept[yy_current_state]) {
                (yy_last_accepting_state)= yy_current_state;
                (yy_last_accepting_cpos)= yy_cp;
            }
            while (yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state) {
                yy_current_state = (int)yy_def[yy_current_state];
                if (yy_current_state >= 90) {
                    yy_c = yy_meta[yy_c];
                }
            }
            yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
            ++yy_cp;
        } while (yy_base[yy_current_state] != 126);

yy_find_action:
    yy_act = yy_accept[yy_current_state];
    if (yy_act == 0) { /* have to back up */
        yy_cp = (yy_last_accepting_cpos);
        yy_current_state = (yy_last_accepting_state);
        yy_act = yy_accept[yy_current_state];
    }
    YY_DO_BEFORE_ACTION;

do_action:    /* This label is used only to access EOF actions. */
            switch (yy_act) { /* beginning of action switch */
                case 0: /* must back up */
                    /* undo the effects of YY_DO_BEFORE_ACTION */
                    *yy_cp = (yy_hold_char);
                    yy_cp = (yy_last_accepting_cpos);
                    yy_current_state = (yy_last_accepting_state);
                    goto yy_find_action;
                case 1:
                    YY_RULE_SETUP {
                        loc.step(); // 注释
                    }
                    YY_BREAK
                case 2:
                    /* rule 2 can match eol */
                    YY_RULE_SETUP {
                        loc.step(); // 注释
                    }
                    YY_BREAK
                case 3:
                case 4:
                    YY_RULE_SETUP {
                        loc.step();
                    }
                    YY_BREAK
                case 5:
                    /* rule 5 can match eol */
                    YY_RULE_SETUP {
                        loc.lines(yyleng); // 使用lines函数来更新位置信息中的行号
                        loc.step();
                    }
                    YY_BREAK
                case 6:
                    YY_RULE_SETUP {
                        return Parser::make_FUNCTION(yytext, loc);
                    }
                    YY_BREAK
                case 7:
                    YY_RULE_SETUP {
                        return Parser::make_FOR(yytext, loc);
                    }
                    YY_BREAK
                case 8:
                    YY_RULE_SETUP {
                        return Parser::make_WHILE(yytext, loc);
                    }
                    YY_BREAK
                case 9:
                    YY_RULE_SETUP {
                        return Parser::make_IF(yytext, loc);
                    } //return IF;
                    YY_BREAK
                case 10:
                    YY_RULE_SETUP {
                        return Parser::make_ELSE(yytext, loc);
                    } //return ELSE;
                    YY_BREAK
                case 11:
                    YY_RULE_SETUP {
                        return Parser::make_ADD(yytext, loc);
                    } //return ADD;
                    YY_BREAK
                case 12:
                    YY_RULE_SETUP {
                        return Parser::make_SUB(yytext, loc);
                    } //return SUB;
                    YY_BREAK
                case 13:
                    YY_RULE_SETUP {
                        return Parser::make_MUL(yytext, loc);
                    } //return MUL;
                    YY_BREAK
                case 14:
                    YY_RULE_SETUP {
                        return Parser::make_DIV(yytext, loc);
                    } //return DIV;
                    YY_BREAK
                case 15:
                    YY_RULE_SETUP {
                        return Parser::make_ASSIGN(yytext, loc);
                    } //return ASSIGN;
                    YY_BREAK
                case 16:
                    YY_RULE_SETUP {
                        return Parser::make_EQ(yytext, loc);
                    } //return EQ;
                    YY_BREAK
                case 17:
                    YY_RULE_SETUP {
                        return Parser::make_AND(yytext, loc);
                    } //return AND;
                    YY_BREAK
                case 18:
                    YY_RULE_SETUP {
                        return Parser::make_OR(yytext, loc);
                    } //return OR;
                    YY_BREAK
                case 19:
                    YY_RULE_SETUP {
                        return Parser::make_NE(yytext, loc);
                    } //return NE;
                    YY_BREAK
                case 20:
                    YY_RULE_SETUP {
                        return Parser::make_GT(yytext, loc);
                    } //return GT;
                    YY_BREAK
                case 21:
                    YY_RULE_SETUP {
                        return Parser::make_GE(yytext, loc);
                    } //return GE;
                    YY_BREAK
                case 22:
                    YY_RULE_SETUP {
                        return Parser::make_LT(yytext, loc);
                    } //return LT;
                    YY_BREAK
                case 23:
                    YY_RULE_SETUP {
                        return Parser::make_LE(yytext, loc);
                    } //return LE;
                    YY_BREAK
                case 24:
                    YY_RULE_SETUP {
                        return Parser::make_LP(yytext, loc);
                    } //return LP;
                    YY_BREAK
                case 25:
                    YY_RULE_SETUP {
                        return Parser::make_RP(yytext, loc);
                    } //return RP;
                    YY_BREAK
                case 26:
                    YY_RULE_SETUP {
                        return Parser::make_LC(yytext, loc);
                    } //return LC;
                    YY_BREAK
                case 27:
                    YY_RULE_SETUP {
                        return Parser::make_RC(yytext, loc);
                    } //return RC;
                    YY_BREAK
                case 28:
                    YY_RULE_SETUP {
                        return Parser::make_SEMICOLON(yytext, loc);
                    } //return SEMICOLON;
                    YY_BREAK
                case 29:
                    YY_RULE_SETUP {
                        return Parser::make_BREAK(yytext, loc);
                    } //return BREAK;
                    YY_BREAK
                case 30:
                    YY_RULE_SETUP {
                        return Parser::make_CONTINUE(yytext, loc);
                    } //return CONTINUE;
                    YY_BREAK
                case 31:
                    YY_RULE_SETUP {
                        return Parser::make_RETURN(yytext, loc);
                    } //return RETURN;
                    YY_BREAK
                case 32:
                    YY_RULE_SETUP {
                        return Parser::make_COMMA(yytext, loc);
                    } //return COMMA;
                    YY_BREAK
                case 33:
                    YY_RULE_SETUP {
                        return Parser::make_IDENTIFIER(yytext, loc);
                    }
                    YY_BREAK
                case 34:
                    YY_RULE_SETUP {
                        const int decimal = 10;
                        return Parser::make_NUMBER(std::strtol(yytext, (&yytext + yyleng), decimal), loc);
                    }
                    YY_BREAK
                case 35:
                    YY_RULE_SETUP {
                        char* end = nullptr;
                        return Parser::make_FLOAT(std::strtof(yytext, &end), loc);
                    }
                    YY_BREAK
                case 36:
                    YY_RULE_SETUP {
                        return Parser::make_STRING(std::string(yytext + 1, yyleng - 2), loc);
                    }
                    YY_BREAK
                case YY_STATE_EOF(INITIAL): {
                    return yyterminate();
                }
                YY_BREAK
                case 37:
                    YY_RULE_SETUP {
                        loc.step();
                    }
                    YY_BREAK
                case 38:
                    YY_RULE_SETUP
                    ECHO;
                    YY_BREAK
                case YY_END_OF_BUFFER: {
                    /* Amount of text matched not including the EOB char. */
                    int yy_amount_of_matched_text = (int)(yy_cp - (yytext_ptr))- 1;
                    /* Undo the effects of YY_DO_BEFORE_ACTION. */
                    *yy_cp = (yy_hold_char);
                    YY_RESTORE_YY_MORE_OFFSET

                    if (YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW) {
                        /* We're scanning a new file or input source.  It's
                         * possible that this happened because the user
                         * just pointed yyin at a new source and called
                         * yylex().  If so, then we have to assure
                         * consistency between YY_CURRENT_BUFFER and our
                         * globals.  Here is the right place to do so, because
                         * this is the first action (other than possibly a
                         * back-up)that will match for the new input source.
                         */
                        (yy_n_chars)= YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
                        YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin.rdbuf();
                        YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
                    }

                    /* Note that here we test for yy_c_buf_p "<=" to the position
                     * of the first EOB in the buffer, since yy_c_buf_p will
                     * already have been incremented past the NUL character
                     * (since all states make transitions on EOB to the
                     * end-of-buffer state).  Contrast this with the test
                     * in input().
                     */
                    if ((yy_c_buf_p)<= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]) { /* This was really a NUL. */
                        yy_state_type yy_next_state;
                        (yy_c_buf_p)= (yytext_ptr)+ yy_amount_of_matched_text;
                        yy_current_state = yy_get_previous_state();
                        /* Okay, we're now positioned to make the NUL
                         * transition.  We couldn't have
                         * yy_get_previous_state()go ahead and do it
                         * for us because it doesn't know how to deal
                         * with the possibility of jamming (and we don't
                         * want to build jamming into it because then it
                         * will run more slowly).
                         */
                        yy_next_state = yy_try_NUL_trans(yy_current_state);
                        yy_bp = (yytext_ptr)+ YY_MORE_ADJ;

                        if (yy_next_state) {
                            /* Consume the NUL. */
                            yy_cp = ++(yy_c_buf_p);
                            yy_current_state = yy_next_state;
                            goto yy_match;
                        } else {
                            yy_cp = (yy_c_buf_p);
                            goto yy_find_action;
                        }
                    } else switch (yy_get_next_buffer()) {
                        case EOB_ACT_END_OF_FILE: {
                            (yy_did_buffer_switch_on_eof)= 0;
                            if (yywrap()) {
                                /* Note: because we've taken care in
                                 * yy_get_next_buffer()to have set up
                                 * yytext, we can now set up
                                 * yy_c_buf_p so that if some total
                                 * hoser (like flex itself)wants to
                                 * call the scanner after we return the
                                 * YY_NULL, it'll still work - another
                                 * YY_NULL will get returned.
                                 */
                                (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;

                                yy_act = YY_STATE_EOF(YY_START);
                                goto do_action;
                            } else {
                                if (!(yy_did_buffer_switch_on_eof)) {
                                    YY_NEW_FILE;
                                }
                            }
                            break;
                        }
                        case EOB_ACT_CONTINUE_SCAN:
                            (yy_c_buf_p)= (yytext_ptr)+ yy_amount_of_matched_text;
                            yy_current_state = yy_get_previous_state();
                            yy_cp = (yy_c_buf_p);
                            yy_bp = (yytext_ptr)+ YY_MORE_ADJ;
                            goto yy_match;
                        case EOB_ACT_LAST_MATCH:
                            (yy_c_buf_p)= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
                            yy_current_state = yy_get_previous_state();
                            yy_cp = (yy_c_buf_p);
                            yy_bp = (yytext_ptr)+ YY_MORE_ADJ;
                            goto yy_find_action;
                        }
                    break;
                }
                default:
                    YY_FATAL_ERROR("fatal flex scanner internal error--no action found");
            } /* end of action switch */
        } /* end of scanning one token */
    } /* end of user's declarations */
} /* end of yylex */

/* The contents of this function are C++ specific, so the ()macro is not used.
 * This constructor simply maintains backward compatibility.
 * DEPRECATED
 */
yyFlexLexer::yyFlexLexer(std::istream* arg_yyin, std::ostream* arg_yyout):
    yyin(arg_yyin ? arg_yyin->rdbuf(): std::cin.rdbuf()),
    yyout(arg_yyout ? arg_yyout->rdbuf(): std::cout.rdbuf())
{
    ctor_common();
}

/* The contents of this function are C++ specific, so the ()macro is not used.
 */
yyFlexLexer::yyFlexLexer(std::istream& arg_yyin, std::ostream& arg_yyout):
    yyin(arg_yyin.rdbuf()),
    yyout(arg_yyout.rdbuf())
{
    ctor_common();
}

/* The contents of this function are C++ specific, so the ()macro is not used.
 */
void yyFlexLexer::ctor_common()
{
    yy_c_buf_p = 0;
    yy_init = 0;
    yy_start = 0;
    yy_flex_debug = 0;
    yylineno = 1;    // this will only get updated if %option yylineno

    yy_did_buffer_switch_on_eof = 0;

    yy_looking_for_trail_begin = 0;
    yy_more_flag = 0;
    yy_more_len = 0;
    yy_more_offset = yy_prev_more_offset = 0;
    yy_start_stack_ptr = yy_start_stack_depth = 0;
    yy_start_stack = NULL;

    yy_buffer_stack = NULL;
    yy_buffer_stack_top = 0;
    yy_buffer_stack_max = 0;

    yy_state_buf = 0;

}

/* The contents of this function are C++ specific, so the ()macro is not used.
 */
yyFlexLexer::~yyFlexLexer()
{
    delete [] yy_state_buf;
    yyfree(yy_start_stack);
    yy_delete_buffer(YY_CURRENT_BUFFER);
    yyfree(yy_buffer_stack);
}

/* The contents of this function are C++ specific, so the ()macro is not used.
 */
void yyFlexLexer::switch_streams(std::istream& new_in, std::ostream& new_out)
{
    // was if(new_in)
    yy_delete_buffer(YY_CURRENT_BUFFER);
    yy_switch_to_buffer(yy_create_buffer(new_in, YY_BUF_SIZE));

    // was if(new_out)
    yyout.rdbuf(new_out.rdbuf());
}

/* The contents of this function are C++ specific, so the ()macro is not used.
 */
void yyFlexLexer::switch_streams(std::istream *new_in, std::ostream *new_out)
{
    if(!new_in) {
        new_in = &yyin;
    }

    if (!new_out) {
        new_out = &yyout;
    }
    switch_streams(*new_in, *new_out);
}

#ifdef YY_INTERACTIVE
int yyFlexLexer::LexerInput(char* buf, int /* max_size */)
#else
int yyFlexLexer::LexerInput(char* buf, int max_size)
#endif
{
    if (yyin.eof()|| yyin.fail()) {
        return 0;
    }
#ifdef YY_INTERACTIVE
    yyin.get(buf[0]);
    if (yyin.eof()) {
        return 0;
    }
    if (yyin.bad()) {
        return -1;
    }
    return 1;
#else
    (void)yyin.read(buf, max_size);
    if (yyin.bad()) {
        return -1;
    } else {
        return yyin.gcount();
    }
#endif
}

void yyFlexLexer::LexerOutput(const char *buf, int size)
{
    (void)yyout.write(buf, size);
}

/* yy_get_next_buffer - try to read in a new buffer
 *
 * Returns a code representing an action:
 *    EOB_ACT_LAST_MATCH -
 *    EOB_ACT_CONTINUE_SCAN - continue scanning from current position
 *    EOB_ACT_END_OF_FILE - end of file
 */
int yyFlexLexer::yy_get_next_buffer()
{
    char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
    char *source = (yytext_ptr);
    int number_to_move, i;
    int ret_val;

    if ((yy_c_buf_p)> &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)+ 1]) {
        YY_FATAL_ERROR("fatal flex scanner internal error--end of buffer missed");
    }
    if (YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0) { /* Don't try to fill the buffer, so this is an EOF. */
        if ((yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1) {
            /* We matched a single character, the EOB, so
             * treat this as a final EOF.
             */
            return EOB_ACT_END_OF_FILE;
        } else {
            /* We matched some text prior to the EOB, first
             * process it.
             */
            return EOB_ACT_LAST_MATCH;
        }
    }
    /* Try to read more data. */
    /* First move last chars to start of buffer. */
    number_to_move = (int)((yy_c_buf_p) - (yytext_ptr)- 1);
    for (i = 0; i < number_to_move; ++i) {
        *(dest++) = *(source++);
    }

    if (YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING) {
        /* don't do the read, it's not guaranteed to return an EOF,
         * just force an EOF
         */
        YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
    } else {
        int num_to_read =
        YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;

        while (num_to_read <= 0) { /* Not enough room in the buffer - grow it. */
            /* just a shorter name for the current buffer */
            YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;
            int yy_c_buf_p_offset = (int)((yy_c_buf_p)- b->yy_ch_buf);

            if (b->yy_is_our_buffer) {
                int new_size = b->yy_buf_size * 2;
                if (new_size <= 0) {
                    b->yy_buf_size += b->yy_buf_size / 8;
                } else {
                    b->yy_buf_size *= 2;
                }

                b->yy_ch_buf = (char *)
                    /* Include room in for 2 EOB chars. */
                    yyrealloc((void *)b->yy_ch_buf,
                             (yy_size_t)(b->yy_buf_size + 2));
            } else {
                /* Can't grow it, we don't own it. */
                b->yy_ch_buf = NULL;
            }

            if (!b->yy_ch_buf) {
                YY_FATAL_ERROR(
                "fatal error - scanner input buffer overflow");
            }
            (yy_c_buf_p)= &b->yy_ch_buf[yy_c_buf_p_offset];
            num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
                        number_to_move - 1;
        }

        if (num_to_read > YY_READ_BUF_SIZE) {
            num_to_read = YY_READ_BUF_SIZE;
        }
        /* Read in more data. */
        YY_INPUT((&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
            (yy_n_chars), num_to_read);
        YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
    }

    if ((yy_n_chars)== 0) {
        if (number_to_move == YY_MORE_ADJ) {
            ret_val = EOB_ACT_END_OF_FILE;
            yyrestart(yyin);
        } else {
            ret_val = EOB_ACT_LAST_MATCH;
            YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING;
       }
    } else {
        ret_val = EOB_ACT_CONTINUE_SCAN;
    }

    if (((yy_n_chars)+ number_to_move)> YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
        /* Extend the array by 50%, plus the number we really need. */
        int new_size = (yy_n_chars) + number_to_move + ((yy_n_chars)>> 1);
        YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *)yyrealloc(
            (void *)YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t)new_size);
        if (!YY_CURRENT_BUFFER_LVALUE->yy_ch_buf)
            YY_FATAL_ERROR("out of dynamic memory in yy_get_next_buffer()");
        /* "- 2" to take care of EOB's */
        YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int)(new_size - 2);
    }

    (yy_n_chars)+= number_to_move;
    YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
    YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
    (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
    return ret_val;
}

/* yy_get_previous_state - get the state just before the EOB char was reached */
yy_state_type yyFlexLexer::yy_get_previous_state()
{
    yy_state_type yy_current_state;
    char *yy_cp;

    yy_current_state = (yy_start);
    for (yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp) {
        YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
        if (yy_accept[yy_current_state]) {
            (yy_last_accepting_state) = yy_current_state;
            (yy_last_accepting_cpos) = yy_cp;
        }
        while (yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state) {
            yy_current_state = (int)yy_def[yy_current_state];
            if (yy_current_state >= 90) {
                yy_c = yy_meta[yy_c];
            }
        }
        yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
    }
    return yy_current_state;
}

/* yy_try_NUL_trans - try to make a transition on the NUL character
 *
 * synopsis
 *    next_state = yy_try_NUL_trans(current_state);
 */
yy_state_type yyFlexLexer::yy_try_NUL_trans(yy_state_type yy_current_state)
{
    int yy_is_jam;
    char *yy_cp = (yy_c_buf_p);

    YY_CHAR yy_c = 1;
    if (yy_accept[yy_current_state]) {
        (yy_last_accepting_state) = yy_current_state;
        (yy_last_accepting_cpos) = yy_cp;
    }
    while (yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state) {
        yy_current_state = (int)yy_def[yy_current_state];
        if (yy_current_state >= 90) {
            yy_c = yy_meta[yy_c];
        }
    }
    yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
    yy_is_jam = (yy_current_state == 89);
    return yy_is_jam ? 0 : yy_current_state;
}

#ifndef YY_NO_UNPUT
void yyFlexLexer::yyunput(int c, char* yy_bp)
{
    char *yy_cp;
    yy_cp = (yy_c_buf_p);

    /* undo effects of setting up yytext */
    *yy_cp = (yy_hold_char);

    if (yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2) { /* need to shift things up to make room */
        /* +2 for EOB chars. */
        int number_to_move = (yy_n_chars)+ 2;
        char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
        char *source = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
        while (source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf) {
            *--dest = *--source;
        }
        yy_cp += (int)(dest - source);
        yy_bp += (int)(dest - source);
        YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = (int)YY_CURRENT_BUFFER_LVALUE->yy_buf_size;

        if (yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2) {
            YY_FATAL_ERROR("flex scanner push-back overflow");
        }
    }
    *--yy_cp = (char)c;
    (yytext_ptr) = yy_bp;
    (yy_hold_char) = *yy_cp;
    (yy_c_buf_p) = yy_cp;
}
#endif

int yyFlexLexer::yyinput()
{
    int c;
    *(yy_c_buf_p) = (yy_hold_char);

    if (*(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR) {
    /* yy_c_buf_p now points to the character we want to return.
    * If this occurs *before* the EOB characters, then it's a
    * valid NUL; if not, then we've hit the end of the buffer.
    */
        if ((yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]) {
            /* This was really a NUL. */
            *(yy_c_buf_p) = '\0';
        } else { /* need more input */
            int offset = (int)((yy_c_buf_p) - (yytext_ptr));
            ++(yy_c_buf_p);
            switch (yy_get_next_buffer()) {
                case EOB_ACT_LAST_MATCH:
                    /* This happens because yy_g_n_b()
                     * sees that we've accumulated a
                     * token and flags that we need to
                     * try matching the token before
                     * proceeding.  But for input(),
                     * there's no matching to consider.
                     * So convert the EOB_ACT_LAST_MATCH
                     * to EOB_ACT_END_OF_FILE.
                     */

                    /* Reset buffer status. */
                    yyrestart(yyin);
                    [[fallthrough]];
                case EOB_ACT_END_OF_FILE: {
                    if (yywrap()) {
                        return 0;
                    }
                    if (!(yy_did_buffer_switch_on_eof)) {
                        YY_NEW_FILE;
                    }
#ifdef __cplusplus
                    return yyinput();
#else
                    return input();
#endif
                }
                case EOB_ACT_CONTINUE_SCAN:
                    (yy_c_buf_p) = (yytext_ptr)+ offset;
                    break;
            }
        }
    }
    c = *(unsigned char *)(yy_c_buf_p);    /* cast for 8-bit char's */
    *(yy_c_buf_p) = '\0';    /* preserve yytext */
    (yy_hold_char) = *++(yy_c_buf_p);
    return c;
}

/** Immediately switch to a different input stream.
 * @param input_file A readable stream.
 *
 * @note This function does not reset the start condition to @c INITIAL .
 */
void yyFlexLexer::yyrestart(std::istream& input_file)
{
    if (!YY_CURRENT_BUFFER) {
        yyensure_buffer_stack();
        YY_CURRENT_BUFFER_LVALUE =
            yy_create_buffer(yyin, YY_BUF_SIZE);
    }

    yy_init_buffer(YY_CURRENT_BUFFER, input_file);
    yy_load_buffer_state();
}

/** Delegate to the new version that takes an istream reference.
 * @param input_file A readable stream.
 *
 * @note This function does not reset the start condition to @c INITIAL .
 */
void yyFlexLexer::yyrestart(std::istream* input_file)
{
    if(!input_file) {
        input_file = &yyin;
    }
    yyrestart(*input_file);
}

/** Switch to a different input buffer.
 * @param new_buffer The new input buffer.
 *
 */
void yyFlexLexer::yy_switch_to_buffer(YY_BUFFER_STATE new_buffer)
{
    /* TODO. We should be able to replace this entire function body
     * with
     *        yypop_buffer_state();
     *        yypush_buffer_state(new_buffer);
     */
    yyensure_buffer_stack ();
    if (YY_CURRENT_BUFFER == new_buffer) {
        return;
    }

    if (YY_CURRENT_BUFFER) {
        /* Flush out information for old buffer. */
        *(yy_c_buf_p)= (yy_hold_char);
        YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
        YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
    }

    YY_CURRENT_BUFFER_LVALUE = new_buffer;
    yy_load_buffer_state();

    /* We don't actually know whether we did this switch during
     * EOF (yywrap())processing, but the only time this flag
     * is looked at is after yywrap()is called, so it's safe
     * to go ahead and always set it.
     */
    (yy_did_buffer_switch_on_eof) = 1;
}

void yyFlexLexer::yy_load_buffer_state()
{
    (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
    (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
    yyin.rdbuf(YY_CURRENT_BUFFER_LVALUE->yy_input_file);
    (yy_hold_char) = *(yy_c_buf_p);
}

/** Allocate and initialize an input buffer state.
 * @param file A readable stream.
 * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
 * 
 * @return the allocated buffer state.
 */
YY_BUFFER_STATE yyFlexLexer::yy_create_buffer(std::istream& file, int size)
{
    YY_BUFFER_STATE b;

    b = (YY_BUFFER_STATE)yyalloc(sizeof(struct yy_buffer_state));
    if (!b) {
        YY_FATAL_ERROR("out of dynamic memory in yy_create_buffer()");
    }

    b->yy_buf_size = size;

    /* yy_ch_buf has to be 2 characters longer than the size given because
     * we need to put in 2 end-of-buffer characters.
     */
    b->yy_ch_buf = (char *)yyalloc((yy_size_t)(b->yy_buf_size + 2));
    if (!b->yy_ch_buf) {
        YY_FATAL_ERROR("out of dynamic memory in yy_create_buffer()");
    }
    b->yy_is_our_buffer = 1;
    yy_init_buffer(b, file);
    return b;
}

/** Delegate creation of buffers to the new version that takes an istream reference.
 * @param file A readable stream.
 * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
 *
 * @return the allocated buffer state.
 */
YY_BUFFER_STATE yyFlexLexer::yy_create_buffer(std::istream *file, int size)
{
    return yy_create_buffer(*file, size);
}

/** Destroy the buffer.
 * @param b a buffer created with yy_create_buffer()
 */
void yyFlexLexer::yy_delete_buffer(YY_BUFFER_STATE b)
{
    if (!b) {
        return;
    }

    if (b == YY_CURRENT_BUFFER) { /* Not sure if we should pop here. */
        YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE)0;
    }

    if (b->yy_is_our_buffer) {
        yyfree((void *)b->yy_ch_buf);
    }
    yyfree((void *)b);
}

/* Initializes or reinitializes a buffer.
 * This function is sometimes called more than once on the same buffer,
 * such as during a yyrestart()or at EOF.
 */
void yyFlexLexer::yy_init_buffer(YY_BUFFER_STATE b, std::istream& file)
{
    int oerrno = errno;

    yy_flush_buffer(b);
    b->yy_input_file = file.rdbuf();
    b->yy_fill_buffer = 1;

    /* If b is the current buffer, then yy_init_buffer was _probably_
     * called from yyrestart()or through yy_get_next_buffer.
     * In that case, we don't want to reset the lineno or column.
     */
    if (b != YY_CURRENT_BUFFER) {
        b->yy_bs_lineno = 1;
        b->yy_bs_column = 0;
    }

    b->yy_is_interactive = 0;
    errno = oerrno;
}

/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
 * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
 *
 */
void yyFlexLexer::yy_flush_buffer(YY_BUFFER_STATE b)
{
    if (!b) {
        return;
    }

    b->yy_n_chars = 0;
    /* We always need two end-of-buffer characters.  The first causes
     * a transition to the end-of-buffer state.  The second causes
     * a jam in that state.
     */
    b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
    b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
    b->yy_buf_pos = &b->yy_ch_buf[0];
    b->yy_at_bol = 1;
    b->yy_buffer_status = YY_BUFFER_NEW;

    if (b == YY_CURRENT_BUFFER) {
        yy_load_buffer_state();
    }
}

/** Pushes the new state onto the stack. The new state becomes
 *  the current state. This function will allocate the stack
 *  if necessary.
 *  @param new_buffer The new state.
 *  
 */
void yyFlexLexer::yypush_buffer_state(YY_BUFFER_STATE new_buffer)
{
    if (new_buffer == NULL) {
        return;
    }

    yyensure_buffer_stack();
    /* This block is copied from yy_switch_to_buffer. */
    if (YY_CURRENT_BUFFER) {
        /* Flush out information for old buffer. */
        *(yy_c_buf_p)= (yy_hold_char);
        YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
        YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
    }

    /* Only push if top exists. Otherwise, replace top. */
    if (YY_CURRENT_BUFFER) {
        (yy_buffer_stack_top)++;
    }
    YY_CURRENT_BUFFER_LVALUE = new_buffer;

    /* copied from yy_switch_to_buffer. */
    yy_load_buffer_state();
    (yy_did_buffer_switch_on_eof) = 1;
}

/** Removes and deletes the top of the stack, if present.
 *  The next element becomes the new top.
 */
void yyFlexLexer::yypop_buffer_state(void)
{
    if (!YY_CURRENT_BUFFER) {
        return;
    }
    yy_delete_buffer(YY_CURRENT_BUFFER);
    YY_CURRENT_BUFFER_LVALUE = NULL;
    if ((yy_buffer_stack_top)> 0) {
        --(yy_buffer_stack_top);
    }
    if (YY_CURRENT_BUFFER) {
        yy_load_buffer_state();
        (yy_did_buffer_switch_on_eof) = 1;
    }
}

/* Allocates the stack if it does not exist.
 *  Guarantees space for at least one push.
 */
void yyFlexLexer::yyensure_buffer_stack(void)
{
    yy_size_t num_to_alloc;

    if (!(yy_buffer_stack)) {
        /* First allocation is just for 2 elements, since we don't know if this
         * scanner will even need a stack. We use 2 instead of 1 to avoid an
         * immediate realloc on the next call.
         */
        num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */
        (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc(num_to_alloc * sizeof(struct yy_buffer_state*));
        if (!(yy_buffer_stack)) {
            YY_FATAL_ERROR("out of dynamic memory in yyensure_buffer_stack()");
        }
        memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
        (yy_buffer_stack_max) = num_to_alloc;
        (yy_buffer_stack_top) = 0;
        return;
    }
    if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max))- 1) {
        /* Increase the buffer to prepare for a possible push. */
        yy_size_t grow_size = 8 /* arbitrary grow size */;

        num_to_alloc = (yy_buffer_stack_max)+ grow_size;
        (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc((yy_buffer_stack),
                                num_to_alloc * sizeof(struct yy_buffer_state*));
        if (!(yy_buffer_stack)) {
            YY_FATAL_ERROR("out of dynamic memory in yyensure_buffer_stack()");
        }
        /* zero only the new slots.*/
        memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
        (yy_buffer_stack_max) = num_to_alloc;
    }
}

void yyFlexLexer::yy_push_state(int _new_state)
{
    if ((yy_start_stack_ptr) >= (yy_start_stack_depth)) {
        yy_size_t new_size;
        (yy_start_stack_depth) += YY_START_STACK_INCR;
        new_size = (yy_size_t)(yy_start_stack_depth) * sizeof(int);

        if (!(yy_start_stack)) {
            (yy_start_stack) = (int *)yyalloc(new_size);
        } else {
            (yy_start_stack) = (int *)yyrealloc((void *)(yy_start_stack), new_size);
        }
        if (!(yy_start_stack)) {
            YY_FATAL_ERROR("out of memory expanding start-condition stack");
        }
    }
    (yy_start_stack)[(yy_start_stack_ptr)++] = YY_START;
    BEGIN(_new_state);
}

void yyFlexLexer::yy_pop_state()
{
    if (--(yy_start_stack_ptr) < 0) {
        YY_FATAL_ERROR("start-condition stack underflow");
    }
    BEGIN((yy_start_stack)[(yy_start_stack_ptr)]);
}

int yyFlexLexer::yy_top_state()
{
    return (yy_start_stack_ptr)> 0 ? (yy_start_stack)[(yy_start_stack_ptr)- 1] : YY_START;
}

#ifndef YY_EXIT_FAILURE
#define YY_EXIT_FAILURE 2
#endif

void yyFlexLexer::LexerError(const char *msg)
{
    std::cerr << msg << std::endl;
    exit(YY_EXIT_FAILURE);
}

/* Redefine yyless()so it works in section 3 code. */
#undef yyless
#define yyless(n)\
    do \
        { \
        /* Undo effects of setting up yytext. */ \
        int yyless_macro_arg = (n); \
        YY_LESS_LINENO(yyless_macro_arg);\
        yytext[yyleng] = (yy_hold_char); \
        (yy_c_buf_p)= yytext + yyless_macro_arg; \
        (yy_hold_char)= *(yy_c_buf_p); \
        *(yy_c_buf_p)= '\0'; \
        yyleng = yyless_macro_arg; \
        } \
    while (0)

/* Accessor  methods (get/set functions)to struct members. */

/*
 * Internal utility routines.
 */

#ifndef yytext_ptr
static void yy_flex_strncpy(char *s1, const char *s2, int n)
{
    for (int i = 0; i < n; ++i) {
        s1[i] = s2[i];
    }
}
#endif

#ifdef YY_NEED_STRLEN
static int yy_flex_strlen(const char *s)
{
    int n;
    for (n = 0; s[n]; ++n) {
    }
    return n;
}
#endif

void *yyalloc(yy_size_t size)
{
    return malloc(size);
}

void *yyrealloc(void *ptr, yy_size_t  size)
{
    /* The cast to (char *)in the following accommodates both
     * implementations that use char* generic pointers, and those
     * that use void* generic pointers.  It works with the latter
     * because both ANSI C and C++ allow castless assignment from
     * any pointer type to void*, and deal with argument conversions
     * as though doing an assignment.
     */
    return realloc(ptr, size);
}

void yyfree(void *ptr)
{
    free((char *)ptr); /* see yyrealloc()for (char *)cast */
}

